﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Security;

namespace MvePublicService
{
	/*
	 * 日本SGI株式会社
	 * ヨハンソン・ヘンリク
	 * johansson@sgi.co.jp
	 * 
	 * Comments:
	 *		Perhaps it would be better to use the SSKKMiniHandler?
	 * 
	 * Change Log:
	 * ---------------------------------------------------------------------------
	 * 2009.01.10	Johansson Henrik		Class Created.
	 * 2009.01.16							Check for empty string before writing
	 *										message to log target.
	 */

	/// <summary>
	/// Contains static methods to handle Errors and Exceptions 
	/// that might occur in the main program. This Service does
	/// not contain any advanced Error/Exception handling, this
	/// class is mostly used as a logging facility.
	/// </summary>
	/// <remarks>INSERT:Creds</remarks>
	internal static class ErrorHandler
	{
		/// <summary>
		/// Set the Target for logging. By default the target is None,
		/// meaning no output is produced from the LogMessage Call.
		/// </summary>
		internal static ErrorLoggingModes LoggingMode =
			ErrorLoggingModes.None;

		/// <summary>
		/// Path to a text file used in combination with the ErrorLoggingMode
		/// of File.
		/// </summary>
		internal static string LogFilePath = string.Empty;

		/// <summary>
		/// Logs a single error message to the current target LoggingMode.
		/// </summary>
		/// <param name="Message">The message to log</param>
		/// <param name="AddLineBreak">Tells whether an extra Line Break 
		/// should be added after the message.</param>
		internal static void LogMessage(string Message, bool AddLineBreak)
		{
			if (string.IsNullOrEmpty(Message))
				throw new ArgumentException(
					MvePublicService.Properties.Resources.LogMessageEmptyOrNull);

			string methodName = "";
			string tyepeName = "";

			//Get some additional data on the current stack frame.
			try
			{
				StackFrame frame = new StackFrame(2, true);
				methodName = frame.GetMethod().Name;
				tyepeName = frame.GetMethod().DeclaringType.FullName;
			}
			catch (ArgumentOutOfRangeException)
			{
				methodName = MvePublicService.Properties.Resources.UnknownMethodName;
				tyepeName = MvePublicService.Properties.Resources.UnknownTypeName;
			}

			string recordLine =
				DateTime.Now.ToShortDateString() + "-" +
						DateTime.Now.ToLongTimeString() + " - " +
						tyepeName + "." + methodName +
						": " + Message;

			switch (ErrorHandler.LoggingMode)
			{
				case ErrorLoggingModes.None:
					break;

				case ErrorLoggingModes.Console:
					Console.WriteLine(recordLine);

					if (AddLineBreak)
						Console.WriteLine();

					break;

				case ErrorLoggingModes.System:
					throw new NotSupportedException(
						MvePublicService.Properties.Resources.LogTargetNotSupported);

				case ErrorLoggingModes.File:
					try
					{
						if (String.IsNullOrEmpty(ErrorHandler.LogFilePath))
						{
							throw new ArgumentException(
								MvePublicService.Properties.Resources.LogFilePathNotSet);
						}

						using (StreamWriter sr = new StreamWriter(
							ErrorHandler.LogFilePath, true))
						{
							sr.WriteLine(recordLine);

							if (AddLineBreak)
								sr.WriteLine();
						}
					}
					catch (ObjectDisposedException ex)
					{
						ErrorHandler.LoggingMode = ErrorLoggingModes.Console;
						ErrorHandler.LogMessage(
							MvePublicService.Properties.Resources.WriteToLogFileFailed +
							ex.Message, true);
					}
					catch (IOException ex)
					{
						ErrorHandler.LoggingMode = ErrorLoggingModes.Console;
						ErrorHandler.LogMessage(
							MvePublicService.Properties.Resources.WriteToLogFileFailed +
							ex.Message, true);
					}
					catch (SecurityException ex)
					{
						ErrorHandler.LoggingMode = ErrorLoggingModes.Console;
						ErrorHandler.LogMessage(
							MvePublicService.Properties.Resources.WriteToLogFileFailed +
							ex.Message, true);
					}

					break;

				default:
					break;
			}

			return;
		}//end:LogMessage
	}

	/// <summary>
	/// Holds possible error logging targets.
	/// </summary>
	internal enum ErrorLoggingModes
	{
		//Do not produce any output
		None,

		//Log to the console using Console.WriteLine
		Console,

		//Writes an entry to the system event log
		System,

		//Log to a text file
		File
	}
}
